home *** CD-ROM | disk | FTP | other *** search
-
- static char rcsid[] = "@(#)$Id: elmalias.c,v 5.2 1993/05/16 20:55:32 syd Exp $";
-
- /*******************************************************************************
- * The Elm Mail System - $Revision: 5.2 $
- *
- * Copyright (c) 1988-1992 USENET Community Trust
- * Copyright (c) 1986,1987 Dave Taylor
- *******************************************************************************
- * Bug reports, patches, comments, suggestions should be sent to:
- *
- * Syd Weinstein, Elm Coordinator
- * elm@DSI.COM dsinc!elm
- *
- *******************************************************************************
- * $Log: elmalias.c,v $
- * Revision 5.2 1993/05/16 20:55:32 syd
- * fix elmalias bug
- * From: chip@chinacat.unicom.com (Chip Rosenthal)
- *
- * Revision 5.1 1993/04/12 02:09:29 syd
- * Initial Checkin
- *
- *
- ******************************************************************************/
-
- /*
- * elmalias - Elm alias database access.
- *
- * This utility will display information from the Elm user and system
- * alias databases. It will expand alias names specified on the command
- * line and display the alias value. If an item on the command line is
- * not a valid alias, then it's value is returned. If no names are
- * specified on the command line then all alises are displayed. Output
- * is formatted by either a user-defined format specifier or one of a
- * number of predefined specifications. The default output format
- * displays just the alias value.
- *
- * The format specifiers are:
- *
- * %a alias (the alias name)
- * %l last_name
- * %n name
- * %c comment
- * %v address (the alias value)
- * %t type (Person, Group, or Unknown)
- *
- * In the case that a command line argument does not correspond to
- * an alias, then %a and %v will evaluate to the argument value and
- * all other items will be empty.
- *
- * Printf-like field widths may be used, e.g. "%-20.20a". Conditionals
- * are bracketed by question marks. For example "?n(%n)?" means format
- * "(%n)" if the "name" is defined, otherwise produce no output. Some
- * backslash sequences (e.g. "\t" == tab) are recognized. Any other
- * characters are displayed as is.
- *
- * Example:
- * $ elmalias -f "alias %a is address \"%v\" ?n(%n)?" chip
- * alias chip is address "chip@chinacat.unicom.com" (Chip Rosenthal)
- *
- * Synopsis:
- * elmalias [-aensuvV] [-f format] [alias ...]
- *
- * Options:
- * -a Display alias name. Equivalent to -f "%-20.20a %v".
- * -e Fully expand alias values.
- * -f fmt User-specified output format.
- * -n Display name. Equivalent to -f "%v?n (%n)?".
- * -r Complain about arguments that are not valid aliases.
- * -s Consult system-wide alias file.
- * -u Consult user-specific alias file.
- * -v Verbose output. Equivalent to -f "%-20.20a %v?n (%n)?".
- * -V Babble about *everything* we known about.
- *
- * If neither -s or -u are specified, then the default is to search
- * both alias files.
- */
-
- #include "elmutil.h"
- #include "ndbz.h"
- #include "s_elmalias.h"
-
- /*
- * Maximum number of alias files we can consult.
- */
- #define MAXDB 2 /* user and system alias files */
-
- /*
- * These are used by the "dbz" routines.
- */
- #ifdef DEBUG
- int debug = 0;
- FILE *debugfile = stderr;
- #endif
-
- char *Progname;
-
- /*
- * "aliasdb" library routines.
- */
- extern struct alias_rec *fetch_alias();
- extern char *next_addr_in_list();
-
- /*
- * Local procedures.
- */
- DBZ *open_user_aliases(), *open_system_aliases();
- struct alias_rec *make_dummy_rec();
- void exp_print_alias(), print_alias();
- char *sel_alias_mem();
-
-
- void usage_error()
- {
- fprintf(stderr, catgets(elm_msg_cat, ElmaliasSet, ElmaliasUsage,
- "usage: %s [-aenrsuvV] [-f format] [alias ...]\n"), Progname);
- exit(1);
- /*NOTREACHED*/
- }
-
-
- /*ARGSUSED*/
- void malloc_fail_handler(proc, size)
- char *proc;
- unsigned size;
- {
- fprintf(stderr, catgets(elm_msg_cat, ElmaliasSet, ElmaliasOutOfMemory,
- "%s: out of memory [could not allocate %d bytes]\n"), Progname, size);
- exit(1);
- /*NOTREACHED*/
- }
-
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- char *out_fmt; /* output printing format */
- int do_user_alias; /* TRUE to examine user alias file */
- int do_system_alias; /* TRUE to examine system alias file */
- int do_expand; /* TRUE to recursively expand aliases */
- int do_complain; /* TRUE to insist args are valid aliases*/
- int numdb; /* number of alias files to consult */
- DBZ *dblist[MAXDB+1]; /* NULL terminated list of files */
- struct alias_rec *ar; /* scratch ptr to expansion of curr name*/
- int d, i;
- extern int optind;
- extern char *optarg;
-
- /*
- * Initialize.
- */
- #ifdef I_LOCALE
- setlocale(LC_ALL, "");
- #endif
- elm_msg_cat = catopen("elm2.4", 0); /* parlez vous francais? */
- safe_malloc_fail_handler = /* install procedure to trap errors in */
- malloc_fail_handler; /* the safe_malloc() routines */
- Progname = argv[0]; /* program name for diag messages */
- do_user_alias = FALSE; /* indicate the user hasn't selected */
- do_system_alias = FALSE; /* any alias files (yet) */
- do_expand = FALSE; /* do not recursively expand groups */
- do_complain = FALSE; /* allow non-aliases on cmd line */
- out_fmt = "%v"; /* default is to just show alias value */
- numdb = 0; /* no alias files opened yet */
-
- /*
- * Crack command line options.
- */
- while ((i = getopt(argc, argv, "aef:nrsuvV")) != EOF) {
- switch (i) {
- case 'a': /* show alias name and value */
- out_fmt = "%-20.20a %v";
- break;
- case 'e': /* recursively expand aliases */
- do_expand = TRUE;
- break;
- case 'f': /* user-specified format */
- out_fmt = optarg;
- break;
- case 'n': /* show alias value and fullname*/
- out_fmt = "%v?n (%n)?";
- break;
- case 'r': /* insist args are valid aliases*/
- do_complain = TRUE;
- break;
- case 's': /* use system-wide alias file */
- do_system_alias = TRUE;
- break;
- case 'u': /* use per-user alias file */
- do_user_alias = TRUE;
- break;
- case 'v': /* verbose output format */
- out_fmt = "%-20.20a %v?n (%n)?";
- break;
- case 'V': /* show the user's life story */
- out_fmt = "\
- Alias:\t\t%a\n\
- Address:\t%v\n\
- Type:\t\t%t\n\
- ?n Name:\t\t%n\n?\
- ?l Last Name:\t%l\n?\
- ?c Comment:\t%c\n?\
- ";
- break;
- default:
- usage_error();
- /*NOTREACHED*/
- }
- }
-
- /*
- * If user didn't request specific alias files then use them all.
- */
- if (!do_system_alias && !do_user_alias)
- do_system_alias = do_user_alias = TRUE;
-
- /*
- * Open up the alias files we need to access, in the order of priority.
- */
- if (do_user_alias && (dblist[numdb] = open_user_aliases()) != NULL)
- ++numdb;
- if (do_system_alias && (dblist[numdb] = open_system_aliases()) != NULL)
- ++numdb;
- dblist[numdb] = NULL;
-
- /*
- * If no names specified on command line then dump all alias files..
- */
- if (optind == argc) {
- if (do_expand) {
- fprintf(stderr, catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasCannotSpecifyExpand,
- "%s: cannot specify \"-e\" when dumping all aliases\n"),
- Progname);
- exit(1);
- }
- for (d = 0 ; dblist[d] != NULL ; ++d) {
- /* assumes file pointer left at first key immediately after open */
- while ((ar = fetch_alias(dblist[d], (char *)NULL)) != NULL) {
- print_alias(out_fmt, ar);
- (void) free((malloc_t)ar);
- }
- }
- exit(0);
- }
-
- /*
- * Expand each name on the command line.
- */
- for (i = optind ; i < argc ; ++i) {
-
- /*
- * Try each of the alias files for a match.
- */
- ar = NULL;
- for (d = 0 ; dblist[d] != NULL ; ++d) {
- if ((ar = fetch_alias(dblist[d], argv[i])) != NULL)
- break;
- }
-
- /*
- * Print the result.
- */
- if (ar == NULL) {
- if (do_complain) {
- fprintf(stderr, catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasUnknownAlias, "%s: \"%s\" is not a known alias\n"),
- Progname, argv[i]);
- exit(1);
- }
- ar = make_dummy_rec(argv[i]);
- print_alias(out_fmt, ar);
- } else if (do_expand && (ar->type & GROUP)) {
- exp_print_alias(dblist[d], out_fmt, ar);
- } else {
- print_alias(out_fmt, ar);
- }
-
- (void) free((malloc_t)ar);
-
- }
-
- exit(0);
- /*NOTREACHED*/
- }
-
-
- DBZ *open_system_aliases()
- {
- return dbz_open(system_data_file, O_RDONLY, 0);
- }
-
-
- DBZ *open_user_aliases()
- {
- char *home, *fname;
- DBZ *db;
- extern char *getenv();
-
- if ((home = getenv("HOME")) == NULL) {
- fprintf(stderr, catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasCannotDetermineHome,
- "%s: cannot determine your HOME directory\n"), Progname);
- exit(1);
- }
- fname = (char *)safe_malloc(strlen(home) + 1 + strlen(ALIAS_DATA) + 1);
- (void) strcat(strcat(strcpy(fname, home), "/"), ALIAS_DATA);
- db = dbz_open(fname, O_RDONLY, 0);
- (void) free((malloc_t)fname);
- return db;
- }
-
-
- /*
- * Cobble up an alias record structure to hold some address info.
- */
- struct alias_rec *make_dummy_rec(val)
- char *val;
- {
- struct alias_rec *ar;
- ar = (struct alias_rec *) safe_malloc(sizeof(struct alias_rec));
- ar->status = 0;
- ar->alias = val;
- ar->last_name = "";
- ar->name = "";
- ar->comment = "";
- ar->address = val;
- ar->type = 0;
- ar->length = 0;
- return ar;
- }
-
-
- /*
- * Recursively expand out a list of addresses and print the expansions.
- */
- void exp_print_alias(db, fmt, ar)
- DBZ *db;
- char *fmt;
- struct alias_rec *ar;
- {
- char *abuf; /* list of addresses we can scribble upon */
- char *acurr; /* pointer to current address within "abuf" */
- char *anext; /* pointer to next address within "abuf" */
- struct alias_rec *ar0;
-
- /*
- * Create a copy of this address we can scribble upon.
- */
- anext = abuf = safe_strdup(ar->address);
- #ifdef lint
- *abuf = '\0'; /* shutup set but not used complaint */
- #endif
-
- /*
- * Go through all of the addresses and expand them out.
- */
- while ((acurr = next_addr_in_list(&anext)) != NULL) {
- if ((ar0 = fetch_alias(db, acurr)) == NULL)
- ar0 = make_dummy_rec(acurr);
- if (ar0->type & GROUP)
- exp_print_alias(db, fmt, ar0);
- else
- print_alias(fmt, ar0);
- (void) free((malloc_t)ar0);
- }
-
- (void) free((malloc_t)abuf);
- }
-
-
- /*
- * Print out alias information according to a format specification.
- */
- void print_alias(fmt, ar)
- char *fmt;
- struct alias_rec *ar;
- {
- char pfmt[64]; /* buffer to hold "%m.ns" formats */
- int in_conditional; /* TRUE if in middle of cond expression */
- int print_enab; /* TRUE if OK to print output */
- char *s;
- int n, c;
-
- print_enab = TRUE;
- in_conditional = FALSE;
-
- while (*fmt != '\0') {
-
- switch (*fmt) {
-
- /*
- * Formatted output.
- */
- case '%':
-
- /*
- * Extract the "%m.n" portion of the format.
- */
- pfmt[0] = *fmt++;
- n = 1;
- while (strchr("-.0123456789", *fmt) != NULL) {
- if (n < sizeof(pfmt)-2)
- pfmt[n++] = *fmt;
- ++fmt;
- }
- pfmt[n++] = 's';
- pfmt[n] = '\0';
-
- /*
- * Determine what we are printing.
- */
- if ((s = sel_alias_mem(ar, *fmt)) == NULL) {
- s = catgets(elm_msg_cat, ElmaliasSet, ElmaliasIllegalFmtChar,
- "<illegal format char>");
- }
-
- /*
- * Print out the formatted field.
- */
- if (print_enab)
- printf(pfmt, s);
- break;
-
- /*
- * Conditional printing.
- */
- case '?':
- if (in_conditional) {
- in_conditional = FALSE;
- print_enab = TRUE;
- } else {
- in_conditional = TRUE;
- s = sel_alias_mem(ar, *++fmt);
- print_enab = (s != NULL && *s != '\0');
- }
- break;
-
- /*
- * Backslash escapes.
- */
- case '\\':
- switch (*++fmt) {
- case 'b': c = '\b'; break;
- case 'f': c = '\f'; break;
- case 'n': c = '\n'; break;
- case 'r': c = '\r'; break;
- case 't': c = '\t'; break;
- default: c = *fmt; break;
- }
- if (print_enab && c != '\0')
- putchar(c);
- break;
-
- /*
- * Non-special character to print.
- */
- default:
- if (print_enab)
- putchar(*fmt);
- break;
-
- }
-
- if (*fmt != '\0')
- ++fmt;
-
- }
-
- putchar('\n');
- }
-
-
- /*
- * Select a member of the alias record structure.
- */
- char *sel_alias_mem(ar, sel)
- struct alias_rec *ar;
- int sel;
- {
- switch (sel) {
- case 'a':
- return ar->alias;
- case 'l':
- return ar->last_name;
- case 'n':
- return ar->name;
- case 'c':
- return ar->comment;
- case 'v':
- return ar->address;
- case 't':
- switch (ar->type & (PERSON|GROUP)) {
- case PERSON:
- return catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasTypePerson, "Person");
- case GROUP:
- return catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasTypeGroup, "Group");
- default:
- return catgets(elm_msg_cat, ElmaliasSet,
- ElmaliasTypeUnknown, "Unknown");
- }
- default:
- return (char *) NULL;
- }
- /*NOTREACHED*/
- }
-
-